发信人: yeung (流星雨), 信区: Mud_Builder        
标  题: server-side trigger 
发信站: BBS 水木清华站 (Mon Jul 26 07:00:39 1999) 
 
 
每当网络速度太慢而导致你的指令无法及时送出的时候,你一定会有 
把机器砸掉的冲动,尤其是看到屏幕突然不动,等传过来的时候已经 
在黄泉路上,实在是很不爽的一种事情. 
 
基于这种考虑,我们提出server-side trigger的概念,即允许用户自 
定义一些简单的trigger,在服务器对用户发出这些信息之前就有机会触发 
这些trigger,执行一系列事先定义好的命令. 
 
和server-side alias一起,client端可以变的更"瘦",最终能彻底淘汰 
zmud是最好了,不过,相信80%的时候,zmud都是在用来快速走路和触发一些 
简单的trigger,然后是timer. 
 
这样一来,虽然比zmud还差些,不过也已经可以用个最破的telnet来舒服的玩 
mud了,包括计划中的简单java-applet-client(当然是放在主页里面啦) 
 
目前server-side trigger只支持子串匹配和正则表达式的匹配,还不能够 
把匹配的变量取出来. 
 
可以匹配带颜色的pattern 
 
int help (object me) 
{ 
        write(@HELP 
指令格式 : trigger <触发信息> <触发后欲执行之命令> 
  
当你从系统接收到<触发信息>的时候,可以让系统自动执行一个 
或者一系列预先定义好的指令(可以是你定义的alias). 
  
例如: 
        'trigger 英俊男子身着布衣走了过来。 hi' 会在 
        出现“英俊男子身着布衣走了过来。”的时候自动执行一个 "hi" 的指令。 
        'trigger' 後不加参数则列出你所有的trigger。 
        'trigger sc' 会消除 sc 这个trigger。 (如果你设定过这个trigger的话) 
        'trigger on' 会打开trigger触发。 
        'trigger off'会关闭trigger的触发。 
        'trigger xxxx $gag' 会不显示所有包含xxxx的信息。比如敲这个指令 
                        'trigger 流星雨 $gag',这样你就看不到他的一切话了。 
        'trigger OnDisconnect quit' 会在你断线的时候自动执行 'quit' 指令, 
                        当然也可以是别的指令 
HELP 
); 
        return 1; 
} 
 
 
发信人: yeung (流星雨), 信区: Mud_Builder        
标  题: 程序实现(1) 
发信站: BBS 水木清华站 (Mon Jul 26 07:02:02 1999) 
 
 
/cmds/usr/trigger.c 
 
// trigger.c 
#include  
 
inherit F_CLEAN_UP; 
 
int main(object me, string arg) 
{ 
        int i; 
        mapping trigger; 
        string verb, replace, *vrbs,cname; 
 
        if( !arg ) { 
                trigger = me->query_all_trigger(); 
                if( !sizeof(trigger) ) { 
                        write("你目前并没有设定任何 trigger。\n"); 
                        me->disable_trigger(); 
                } else  { 
                        i = me->query_trigger_enabled(); 
                        me->disable_trigger(); 
                        write("你目前设定的 trigger 有:\n"); 
                        vrbs = keys(trigger); 
                        for(i=0; i < sizeof(vrbs); i++) 
                                printf("%-40s 将触发如下命令:  %s\n", vrbs[i]+NOR, trigger[vrbs[i]]); 
                        write("\n你的触发器目前是"+(i?"打开的":"关闭的")+"。\n"); 
                        if( i ) me->enable_trigger(); 
                } 
                return 1; 
        } 
 
        if( arg=="on" ) 
        { 
                me->enable_trigger(); 
                write("打开trigger触发。\n"); 
                return 1; 
        } 
        if( arg=="off" ) 
        { 
                me->disable_trigger(); 
                write("关闭trigger触发。\n"); 
                return 1; 
        }                        
                cname = arg; 
                cname = replace_string(cname, "$BLK$", BLK); 
                cname = replace_string(cname, "$RED$", RED); 
                cname = replace_string(cname, "$GRN$", GRN); 
                cname = replace_string(cname, "$YEL$", YEL); 
                cname = replace_string(cname, "$BLU$", BLU); 
                cname = replace_string(cname, "$MAG$", MAG); 
                cname = replace_string(cname, "$CYN$", CYN); 
                cname = replace_string(cname, "$WHT$", WHT); 
                cname = replace_string(cname, "$HIR$", HIR); 
                cname = replace_string(cname, "$HIG$", HIG); 
                cname = replace_string(cname, "$HIY$", HIY); 
                cname = replace_string(cname, "$HIB$", HIB); 
                cname = replace_string(cname, "$HIM$", HIM); 
                cname = replace_string(cname, "$HIC$", HIC); 
                cname = replace_string(cname, "$HIW$", HIW); 
                cname = replace_string(cname, "$NOR$", NOR);          
                arg = cname; 
 
        if( sscanf(arg, "%s %s", verb, replace)!=2 ) 
                me->set_trigger(arg, 0); 
        else if( verb=="trigger" ) 
                return notify_fail("你不能将 \"trigger\" 指令设定为 pattern 。\n"); 
        else if( verb=="" )              
                return notify_fail("你要设什麽 trigger?\n"); 
        else 
        { 
                return me->set_trigger(verb, replace); 
        } 
 
        write("Ok.\n"); 
        return 1; 
} 
 
int help (object me) 
{ 
        write(@HELP 
指令格式 : trigger <触发信息> <触发后欲执行之命令> 
  
当你从系统接收到<触发信息>的时候,可以让系统自动执行一个 
或者一系列预先定义好的指令(可以是你定义的alias). 
  
例如: 
        'trigger 英俊男子身着布衣走了过来。 hi' 会在 
        出现“英俊男子身着布衣走了过来。”的时候自动执行一个 "hi" 的指令。 
        'trigger' 後不加参数则列出你所有的trigger。 
        'trigger sc' 会消除 sc 这个trigger。 (如果你设定过这个trigger的话) 
        'trigger on' 会打开trigger触发。 
        'trigger off'会关闭trigger的触发。 
        'trigger xxxx $gag' 会不显示所有包含xxxx的信息。比如敲这个指令 
                        'trigger 流星雨 $gag',这样你就看不到他的一切话了。 
        'trigger OnDisconnect quit' 会在你断线的时候自动执行 'quit' 指令, 
                        当然也可以是别的指令 
HELP 
); 
        return 1; 
} 
 
发信人: yeung (流星雨), 信区: Mud_Builder        
标  题: 程序实现(2) 
发信站: BBS 水木清华站 (Mon Jul 26 07:03:21 1999) 
 
 
/feature/trigger.c 
 
#define MAX_TRIGGERS 10 
 
mapping trigger; 
static int      allow_trigger; 
 
int set_trigger(string verb, string replace) 
{ 
        if( !replace ) { 
                if( mapp(trigger) ) map_delete(trigger, verb); 
                return 1; 
        } else { 
                if( !mapp(trigger) ) trigger = ([ verb:replace ]); 
                else if( sizeof(trigger) > MAX_TRIGGERS ) 
                        return notify_fail("您设定的 trigger 太多了,请先删掉一些不常用的。\n"); 
                else trigger[verb] = replace; 
                return 1; 
        } 
} 
 
mapping query_all_trigger() 
{ 
        return trigger; 
} 
 
void disable_trigger() 
{ 
        allow_trigger = 0; 
} 
 
void enable_trigger() 
{ 
        allow_trigger = 1; 
} 
 
int query_trigger_enabled() 
{ 
        return allow_trigger; 
} 
 
int fire_trigger(string pattern) 
{ 
        string cmd,*patterns; 
        int i,s; 
        object me; 
         
        if( !allow_trigger ) return 0; 
        me = this_object(); 
        if( me->query_temp("parseing") ) return 0; 
        if( !mapp(trigger) ) return 0; 
        pattern = replace_string(pattern,"> ",""); 
         
        patterns = keys(trigger); 
        s = sizeof(patterns); 
        for(i=0;i < s;i++) 
        { 
         
                if( strsrch(pattern,patterns[i]) != -1 || regexp(pattern,patterns[i]) ) 
                { 
                        cmd = trigger[patterns[i]];              
                        if( stringp(cmd) ) 
                        { 
                                if( cmd == "$gag" ) return -999; 
                                //防止有人用quit来避免死亡 
                                me->check_status(); 
                                me->set_temp("parseing",1);              
                                tell_object(me,"触发指令:"+cmd+"\n");                   
                                me->fcommand( me->process_input(cmd) ); 
                                me->delete_temp("parseing"); 
                                return 1; 
                        }        
                } 
        } 
        return 0; 
 
} 
 
发信人: yeung (流星雨), 信区: Mud_Builder        
标  题: 程序实现(3) 
发信站: BBS 水木清华站 (Mon Jul 26 07:05:18 1999) 
 
 
/include/globals.h的改动 
加一个 
#define F_TRIGGER "/feature/trigger" 
 
/std/char.c的改动. 
加一个 
inherit F_TRIGGER; 
 
/feature/message.c的改动 
 
void receive_message(string msgclass, string msg) 
{ 
        string subclass, *ch; 
 
        if( !interactive(this_object()) ) { 
                this_object()->relay_message(msgclass, msg); 
                return; 
        } 
 
        if( sscanf(msgclass, "%s:%s", subclass, msgclass)==2 ) { 
                switch(subclass) { 
                        case "channel": 
                                if( !pointerp(ch = query("channels")) 
                                ||      member_array(msgclass, ch)==-1 ) 
                                        return; 
                                break; 
                        case "outdoor": 
                                if( !environment() || !environment()->query("outdoors") ) 
                                        return; 
                                break; 
//                      default: 
//                              error("Message: Invalid Subclass " + subclass + ".\n"); 
                } 
        } 
 
        if( query_temp("block_msg/all") || query_temp("block_msg/" + msgclass) ) 
                return; 
         
        if( stringp(msg) ) 
        { 
                //支持server-side trigger 
                if( (this_object()->fire_trigger(msg)) == -999) return; 
        } 
         
        if( in_input(this_object()) || in_edit(this_object()) ) { 
                if( sizeof(msg_buffer) < MAX_MSG_BUFFER ) 
                        msg_buffer += ({ msg }); 
        } else 
                receive( msg ); 
} 

发信人: yeung (流星雨), 信区: Mud_Builder        
标  题: 关于以上文档的声明 
发信站: BBS 水木清华站 (Mon Jul 26 07:07:54 1999) 
 
 
未经许可不得用于商业用途. 
非盈利性组织可以基于GNU的精神随意修改及使用上述文档,但是请注明原作者. 
作者:YEUNG